package vn.vfriends.id.ws;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vn.vfriends.id.jpa.entity.Group;
import vn.vfriends.id.jpa.entity.User;
import vn.vfriends.id.service.AccountService;
import vn.vfriends.id.service.GroupService;
import vn.vfriends.id.service.UserService;
import vn.vfriends.id.util.Constants;
import vn.vfriends.id.ws.exception.WSException;

/**
 *
 * @author tuan@vfriends.vn
 */
@WebService(serviceName = "UserWS")
public class UserWS {

    private static final Logger logger = LoggerFactory.getLogger(UserWS.class);
    @Inject
    private UserService userService;
    @Inject
    private GroupService groupService;
    @Inject
    private AccountService accountService;
    @Resource
    private WebServiceContext wsContext;

    private boolean authenticate() {
        MessageContext messageContext = wsContext.getMessageContext();
        Map headers = (Map) messageContext.get(MessageContext.HTTP_REQUEST_HEADERS);
        List userList = (List) headers.get(Constants.WS_USERNAME);
        List passList = (List) headers.get(Constants.WS_USERNAME);

        String username = (userList != null) ? userList.get(0).toString() : "";
        String password = (passList != null) ? passList.get(0).toString() : "";

        if ("wsuser".equals(username) && "wsuser".equals(password)) {
            return true;
        } else {
            return false;
        }
    }

    @WebMethod(operationName = "findUserByUsername")
    public User findUserByUsername(@WebParam(name = "username") String username) throws WSException {
        try {
            boolean isAuthenticated = this.authenticate();
            if (!isAuthenticated) {
                logger.info("Authentication failed");
                throw new WSException(WSException.AUTHENTICATION_FAILED, "Authentication failed");
            } else {
                return userService.findByUsername(username);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new WSException(WSException.ERROR, e.getMessage());
        }
    }

    @WebMethod(operationName = "findUserByEmail")
    public User findUserByEmail(@WebParam(name = "email") String email) throws WSException {
        try {
            boolean isAuthenticated = this.authenticate();
            if (!isAuthenticated) {
                logger.info("Authentication failed");
                throw new WSException(WSException.AUTHENTICATION_FAILED, "Authentication failed");
            } else {
                return userService.findByEmail(email);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new WSException(WSException.ERROR, e.getMessage());
        }
    }

    @WebMethod(operationName = "createCustomer")
    public User createCustomer(@WebParam(name = "email") String email, @WebParam(name = "fullName") String fullName) throws WSException {
        try {
            boolean isAuthenticated = this.authenticate();
            if (!isAuthenticated) {
                logger.info("Authentication failed");
                throw new WSException(WSException.AUTHENTICATION_FAILED, "Authentication failed");
            } else {
                User user = new User();
                user.setUsername(email);
                user.setEmail(email);
                user.setFullName(fullName);
                user.setActivated(true);
                user.setExternal(true);
                
                //  Group
                Group group = this.groupService.findByCode(Group.GroupCode.CUSTOMER);
                if (group != null) {
                    List<Group> groupList = new ArrayList<Group>();
                    groupList.add(group);
                    user.setGroups(groupList);
                }

                userService.create(user);

                // Generate CIF
                String cif = accountService.generateCif(user.getId(), new Long(1000));
                user.setCif(cif);

                userService.edit(user);

                return user;
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new WSException(WSException.ERROR, e.getMessage());
        }
    }
}
